package csc.fresher.view;

import java.io.IOException;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import csc.fresher.commons.BankingConstant;
import csc.fresher.dao.CustomerDao;
import csc.fresher.entity.AccountState;
import csc.fresher.entity.Customer;
import csc.fresher.entity.CustomerAccount;
import csc.fresher.entity.CustomerAccountOverall;
import csc.fresher.entity.DepositTransaction;
import csc.fresher.entity.SystemUser;
import csc.fresher.entity.TransactionState;
import csc.fresher.entity.TransactionType;
import csc.fresher.service.DepositAccountService;
import csc.fresher.service.DepositAccountTransactionService;
import csc.fresher.service.SystemUserService;

@Component
@Scope("session")
public class DepositAccountTransferFundsManageBean implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	@Autowired
	DepositAccountTransactionService depositAccountTransactionService;
	@Autowired
	CustomerDao customerDao;
	@Autowired
	DepositAccountService depositAccountService;
	@Autowired
	private SystemLoginManageBean systemLoginManageBean;
	@Autowired
	private SystemUserService systemUserService;
	
	private Customer sender;
	private Customer receiver;
	private List<CustomerAccountOverall> searchResult;
	private CustomerAccount senderAccount;
	private CustomerAccount receiverAccount;
	private DepositTransaction transaction;
	private double transferAmount;
	private double receiverBalanceAfter;
	private double senderBalanceAfter;
	private Timestamp transactionTime;
	private long searchCustomerIDCard;
	private SystemUser systemUser;
	private long selectedAccountID;
	
	
	public void onLoad() {
		
		if(systemLoginManageBean.getSystemUser() == null) {
			try {
				FacesContext.getCurrentInstance().getExternalContext().redirect("/csc_final/templates3/Logon.jsf");
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			systemUser = systemLoginManageBean.getSystemUser();
			List<Long> listrole = systemUserService.getRoleByUserName(systemUser.getUserName());			
			boolean result = checkRole(listrole);
			if(result == false) {
				try {
					FacesContext.getCurrentInstance().getExternalContext().redirect("/csc_final/Group1/AccountManagement.xhtml");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public boolean checkRole(List<Long> listRole) {
		
		for(int i = 0; i < listRole.size(); i++) {
			if (BankingConstant.ROLE_ACCOUNT_ADMIN == listRole.get(i) || BankingConstant.ROLE_ACCOUNT_SUPPORT == listRole.get(i)){
				return true;
			}
		}		
		return false;
	}
	
	
	public String getSenderInfo(){
		searchResult = new ArrayList<>();
		searchCustomerIDCard = 0;
		FacesContext fc = FacesContext.getCurrentInstance();
	    Map<String,String> params =  fc.getExternalContext().getRequestParameterMap();
	    
	    String strID= params.get("selectedAccountID");
	    try{
	    	this.selectedAccountID  = Long.parseLong(strID);
	    }
	    catch(NumberFormatException e){
	    	FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Null Account"));
			return "";
	    }
	    
		this.senderAccount = depositAccountService
				.getDepositAccountByDepositAccountID(selectedAccountID);
		if (senderAccount == null) {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Null Account"));
			return "";
		}
		if (!senderAccount.getAccountState().getState().equals(AccountState.ACTIVE.getState())) {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("This account can't perform transaction!"));
			return "";
		}
		if (senderAccount != null) {
			this.sender = customerDao.getCustomerByID(senderAccount.getCustomerID());
		}
		
		return "transferSearch";
	}
	
	public String searchReceiver(){
		List<CustomerAccountOverall> listAccountOveralls = depositAccountService.getAccountByIDCardNumber(this.searchCustomerIDCard, "DepositAccount");
		this.setSearchResult(listAccountOveralls);
		return "transferSearch";
	}
	
	public String getReceiverInfo(long receiverID){
		this.transferAmount = 0;
		this.receiverAccount = depositAccountService.getDepositAccountByDepositAccountID(receiverID);
		if (receiverAccount == null) {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Null Account"));
			return "transferSearch";
		}
		if (!receiverAccount.getAccountState().getState().equals(
				AccountState.ACTIVE.getState())) {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("This account can't perform transaction!"));
			return "transferSearch";
		}
		if (receiverAccount != null) {
			this.receiver = customerDao.getCustomerByID(receiverAccount.getCustomerID());
		}
		return "transferFund";
	}
	
	public String confirmTransfer(){
		if(this.transferAmount <=0){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("The transfer money must be larger than 0"));
			return "transferFund";
		}
		double senderAB = senderAccount.getAccountBalance() - this.transferAmount;
		double receiverAB = receiverAccount.getAccountBalance() + this.transferAmount;
		if(senderAB < 0){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("This account doesn't have enough money"));
			return "transferFund";
		}
		this.senderBalanceAfter = senderAB;
		this.receiverBalanceAfter = receiverAB;
		return "transferConfirm";
	}
	
	public String completeTransfer(){
		systemUser = systemLoginManageBean.getSystemUser();
		Timestamp currentTime = new Timestamp(System.currentTimeMillis());
		this.transactionTime = currentTime;
		this.transaction = new DepositTransaction(transferAmount, transactionTime, transactionTime, senderAccount.getAccountBalance(), senderBalanceAfter, 
				TransactionType.TRANSFER, receiverAccount.getAccountNumber(), senderAccount.getAccountNumber(), 
				TransactionState.HOLD, senderAccount.getAccountNumber(), 30000L, BankingConstant.DEFAULT_SYSTEM_USER_ID, false, "");
		
		long returnID = depositAccountTransactionService.transferFunds(transaction);
		if(returnID > 0){
			return "transferComplete";
		}
		else{
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Transaction fail! Please try again!"));
			return "transferConfirm";
		}
	}
	
	public Customer getSender() {
		return sender;
	}
	public void setSender(Customer sender) {
		this.sender = sender;
	}
	public Customer getReceiver() {
		return receiver;
	}
	public void setReceiver(Customer receiver) {
		this.receiver = receiver;
	}
	public CustomerAccount getSenderAccount() {
		return senderAccount;
	}
	public void setSenderAccount(CustomerAccount senderAccount) {
		this.senderAccount = senderAccount;
	}
	public CustomerAccount getReceiverAccount() {
		return receiverAccount;
	}
	public void setReceiverAccount(CustomerAccount receiverAccount) {
		this.receiverAccount = receiverAccount;
	}
	public DepositTransaction getTransaction() {
		return transaction;
	}
	public void setTransaction(DepositTransaction transaction) {
		this.transaction = transaction;
	}
	
	public double getTransferAmount() {
		return transferAmount;
	}
	public void setTransferAmount(double transferAmount) {
		this.transferAmount = transferAmount;
	}
	
	public Timestamp getTransactionTime() {
		return transactionTime;
	}
	public void setTransactionTime(Timestamp transactionTime) {
		this.transactionTime = transactionTime;
	}

	public List<CustomerAccountOverall> getSearchResult() {
		return searchResult;
	}

	public void setSearchResult(List<CustomerAccountOverall> searchResult) {
		this.searchResult = searchResult;
	}
	
	public long getSearchCustomerIDCard() {
		return searchCustomerIDCard;
	}

	public void setSearchCustomerIDCard(long searchCustomerIDCard) {
		this.searchCustomerIDCard = searchCustomerIDCard;
	}

	public double getReceiverBalanceAfter() {
		return receiverBalanceAfter;
	}

	public void setReceiverBalanceAfter(double receiverBalanceAfter) {
		this.receiverBalanceAfter = receiverBalanceAfter;
	}

	public double getSenderBalanceAfter() {
		return senderBalanceAfter;
	}

	public void setSenderBalanceAfter(double senderBalanceAfter) {
		this.senderBalanceAfter = senderBalanceAfter;
	}

	public SystemUser getSystemUser() {
		return systemUser;
	}

	public void setSystemUser(SystemUser systemUser) {
		this.systemUser = systemUser;
	}

	public long getSelectedAccountID() {
		return selectedAccountID;
	}

	public void setSelectedAccountID(long selectedAccountID) {
		this.selectedAccountID = selectedAccountID;
	}
	
	
}
